/***********************************************************************************
Copy right:	    hqyj Tech.
Author:         jiaoyue
Date:           2023.07.01
Description:    http请求处理
***********************************************************************************/

#include <sys/types.h>
#include <sys/socket.h>
#include "custom_handle.h"
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "custom_handle.h"
#include <unistd.h>
#include <stdio.h>
#include <modbus.h>
#include <pthread.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include "cJSON.h"
#include "pub_define.h"
#include "shmem.h"
#include "msg_queue_peer.h"
#define KB 1024
#define HTML_SIZE (64 * KB)

//普通的文本回复需要增加html头部
#define HTML_HEAD "Content-Type: text/html\r\n" \
				  "Connection: close\r\n"


extern struct shm_param para; 
extern struct device *total;
extern struct data*p;
extern struct data*node_arr;

char *serialization()
{
    char buf[32] = "";
    char yyint[32] = "";
    cJSON *root = cJSON_CreateObject();
    cJSON *stm32 = cJSON_CreateObject();
    cJSON *device = cJSON_CreateArray();
    cJSON_AddItemToObject(root,"type",cJSON_CreateNumber(1));
    cJSON *modbusData = cJSON_CreateArray();
    struct data *p = (struct data *)(total + 1);
    for (int i = 0; i < (total->stm32Num + total->modbusNum); i++)
    {
        cJSON *item = cJSON_CreateObject();
        cJSON_AddItemToObject(item, "key", cJSON_CreateNumber(p->key));
        switch (p->type)
        {
        case 1:
            sprintf(yyint,"%d",p->val.b_val);
            cJSON_AddItemToObject(item, "val", cJSON_CreateString(yyint));
            memset(yyint,0,32);
            break;
        case 2:
            sprintf(yyint,"%d",p->val.b_val);
            cJSON_AddItemToObject(item, "val", cJSON_CreateString(yyint));
            memset(yyint,0,32);
            break;
        case 3:
            sprintf(buf,"%.2f",p->val.f_val);
            cJSON_AddItemToObject(item, "val", cJSON_CreateString(buf));
            memset(buf,0,32);
            break;
        default:
            break;
        }
        p++;
        cJSON_AddItemToArray(device, item);
    }
    cJSON_AddItemToObject(root, "data", device);
    char *json_str = cJSON_Print(root);
    cJSON_Delete(root);
    return json_str;
}
static int handle_login(int sock, const char *input)
{
    char reply_buf[HTML_SIZE] = {0};
    char *uname = strstr(input, "username=");
    uname += strlen("username=");
    char *p = strstr(input, "password");
    *(p - 1) = '\0';
    printf("username = %s\n", uname);

    char *passwd = p + strlen("password=");
    printf("passwd = %s\n", passwd);

    if(strcmp(uname, "admin")==0 && strcmp(passwd, "admin")==0)
    {
        sprintf(reply_buf, "<script>localStorage.setItem('usr_user_name', '%s');</script>", uname);
        strcat(reply_buf, "<script>window.location.href = '/index.html';</script>");
        send(sock,reply_buf,strlen(reply_buf),0);
    }
    else
    {
        printf("web login failed\n");
        //"用户名或密码错误"提示，chrome浏览器直接输送utf-8字符流乱码，没有找到太好解决方案，先过渡
        char out[128] = {0xd3,0xc3,0xbb,0xa7,0xc3,0xfb,0xbb,0xf2,0xc3,0xdc,0xc2,0xeb,0xb4,0xed,0xce,0xf3};
        sprintf(reply_buf, "<script charset='gb2312'>alert('%s');</script>", out);
        strcat(reply_buf, "<script>window.location.href = '/login.html';</script>");
        send(sock,reply_buf,strlen(reply_buf),0);
    }

    return 0;
}

static int handle_add(int sock, const char *input)
{
    int number1, number2;
    
    //input必须是"data1=1data2=6"类似的格式，注意前端过来的字符串会有双引号
    sscanf(input, "\"data1=%ddata2=%d\"", &number1, &number2);
    printf("num1 = %d\n", number1);

    char reply_buf[HTML_SIZE] = {0};
    printf("num = %d\n", number1+number2);
    sprintf(reply_buf, "%d", number1+number2);
    printf("resp = %s\n", reply_buf);
    send(sock,reply_buf,strlen(reply_buf),0);

    return 0;
}

/**
 * 功能用于将int类型的数据挂树
 * 无返回值
 */
void aitooi(cJSON *item, cJSON *root, const char *key, int val)
{
    item = cJSON_CreateNumber(val);
    cJSON_AddItemToObject(root, key, item);
}

/**
 * 功能用于将float类型的数据挂树
 * 无返回值
 */
void aitoof(cJSON *item, cJSON *root, const char *key, float val)
{
    item = cJSON_CreateNumber(val);
    cJSON_AddItemToObject(root, key, item);
}

 int mymodbusget(int sock)
 {
    printf("开始读取共享内存\n");
    printf("----------------%d", __LINE__);
    char *q=serialization();
    printf("等待上传的JSON格式的字符串: %s\n", q);
    send(sock, q, strlen(q), 0);
    printf("上传完成");
    free(q);
    return 1;
 }

 int mymodbusset(int sock, cJSON *root)
{
    printf("解析网页端传过来的类型为2的JSON 命令\n");
    // 从root节点获取login节点
    printf("%s\n",cJSON_Print(root));
    cJSON *data = cJSON_GetObjectItem(root, "data");
    cJSON *item = NULL;
    printf("11\n");
    struct message send_buf = {
        .datatype = 100, // long类型的，无所谓 到时候再改
        //  .type = 2,
    };
    struct data *temp = (struct data*)(total+1);
    // printf("%s\n",send_buf.key);
    // 从login节点获取pwd节点
    item = cJSON_GetObjectItem(data, "key");
    printf("%s = %s\n", item->string, item->valuestring);
    cJSON *item1 = cJSON_GetObjectItem(data, "val");
    printf("%s = %d\n", item1->string, item1->valueint);
    for (int i = 0; i < (total->modbusNum+total->stm32Num); i++)
    {
        if (!strcmp(item->valuestring,temp->name))
        {
            send_buf.key = temp->key;
            send_buf.type = temp->type;
            switch (temp->type)
            {
            case 1:
                send_buf.val.b_val = item1->valueint;
                break;
            case 2:
                send_buf.val.i_val = item1->valueint;
                break;
            case 3:
                send_buf.val.f_val = item1->valuedouble;
                break;
            default:
                break;
            }
            if (temp->key / 100 == 3)
            {
                msg_queue_send("stm32", &send_buf, sizeof(send_buf), 0);
            }
            else if (temp->key / 100 == 1)
            {
                msg_queue_send("modbus", &send_buf, sizeof(send_buf), 0);
            }
            break;
        }
        else
        {
            temp++;
        }
    }
    char str[] = "send ok!!!\n";
    send(sock, str, strlen(str), 0);
    cJSON_Delete(root); // 删除树
    return 1;
}
/**
 * @brief 处理自定义请求，在这里添加进程通信
 * @param input
 * @return
 */
int parse_and_process(int sock, const char *query_string, const char *input)
{
    
    //query_string不一定能用的到
    //先处理登录操作
    if(strstr(input, "username=") && strstr(input, "password="))
    {
        return handle_login(sock, input);
    }
    //处理求和请求
    else if(strstr(input, "data1=") && strstr(input, "data2="))
    {
        return handle_add(sock, input);
    }
    else  //剩下的都是json请求，这个和协议有关了
    {
       // 构建要回复的JSON数据
        
        const char *json_response = "{\"message\": \"I don't now!\"}";
        // 这里的input是json格式的请求
        printf("input = %s\n", input);
        // 将网页传来的Json反序列化
        cJSON *root = cJSON_Parse(input);
        if (NULL == root)
        {
            printf("parse err\n");
            return -1;
        }
        cJSON *item = cJSON_GetObjectItem(root, "type");
          printf("type = %d\n", item->valueint);
        switch (item->valueint)
        {
        case 1:                 // 采集模式
            mymodbusget(sock);  // 默认全部采集并且是刷新上报模式
            //cJSON_Delete(root); // 删除树
            break;
        case 2: // 下发指令
            return mymodbusset(sock, root);
            // 在函数里已经完成了删除树的操作
            break;
        case 3: // 修改上报模式   // 上报模式分为三种 刷新上报 变化上报 周期上报
            break;
        case 4: // 历史记录
            break;
        default:
            send(sock, json_response, strlen(json_response), 0);
            break;
       }
        //  const char* json_response = "{\"type\": 1,\"data\":[{\"key\":103,\"val\":\"15.5\"},{\"key\":104,\"val\":\"11.8\"}, {\"key\":105,\"val\":\"45\"}]}";
        // printf("%s\n",json_response);
        // 发送HTTP响应给客户端
        //mymodbusset(sock,root);
        //  const char* json_response = "{\"type\": 1,\"data\":[{\"key\":101,\"val\":\"15.5\"},{\"key\":102,\"val\":\"11.8\"}, {\"key\":103,\"val\":\"1\"} ,{\"key\":104,\"val\":\"45\"}, {\"key\":105,\"val\":\"1\"} ,{\"key\":106,\"val\":\"45\"}, {\"key\":107,\"val\":\"1\"} ,{\"key\":108,\"val\":\"45\"},{\"key\":306,\"val\":\"1\"},{\"key\":303,\"val\":\"1\"},{\"key\":304,\"val\":\"45\"},{\"key\":305,\"val\":\"1\"},{\"key\":307,\"val\":\"1\"},{\"key\":308,\"val\":\"1\"},{\"key\":309,\"val\":\"1\"},{\"key\":310,\"val\":\"1\"},{\"key\":311,\"val\":\"45\"}]}";
        //  send(sock, json_response, strlen(json_response), 0);
    }

    return 0;
}
